#include "common.h"
#include "main.h"
#include "oled.h"
#include "InternalFlash.h"
#include "beep.h"

// 显示菜单
static uint8_t gucMenuIndex = eMENU_INDEX_INPUT_SLEEP;
// 开锁密码
static uint32_t gulPassword = 0;
// 报警标志
static uint8_t gucBeepAlarmFlag = 0;


/**
 * @brief   从flash中读取解锁密码
 * @param   void
 * @retval  void
 */
void vRead_Password(void)
{
    uint8_t pReadValue[4] = {0};

    Internal_Flash_Read( mSYSTEM_CONFIG_PARAMS_SAVE_ADDR, pReadValue, sizeof(pReadValue) );

    gulPassword = (pReadValue[0] << 0) | (pReadValue[1] << 8) | (pReadValue[2] << 16) | (pReadValue[3] << 24);

    return;
}

/**
 * @brief   获取解锁密码
 * @param   void
 * @retval  uint32_t 解锁密码
 */
uint32_t ulGet_Password(void)
{
    return gulPassword;
}

/**
 * @brief   更新密码到flash中
 * @param   uint32_t ulNewValue  新密码
 * @retval  void
 */
void vUpdate_Password(uint32_t ulNewValue)
{
    gulPassword = ulNewValue;

    Internal_Flash_Write( mSYSTEM_CONFIG_PARAMS_SAVE_ADDR, ( uint8_t * )( &gulPassword ), sizeof( gulPassword ) );

    return;
}


/**
 * @brief   清除显示屏某一行的显示
 * @param   uint8_t ucLineNum  行号
 * @retval  void
 */
void vClear_One_Line(uint8_t ucLineNum)
{
    if((ucLineNum >= 1) && (ucLineNum <= 4))
    {
        OLED_ShowString( 0, (ucLineNum - 1) * 16, "                ", 16 );
    }

    return;
}


/**
 * @brief   清除显示屏234行的显示内容
 * @param   void
 * @retval  void
 */
void vClear_Line_234(void)
{
    int i;

    for(i = 2; i <= 4; ++i)
    {
        vClear_One_Line(i);
    }

    return;
}


/**
 * @brief   在显示屏中显示输入密码的方框
 * @param   void
 * @retval  void
 */
void vDisp_Password_Square(void)
{
    int i;

    for(i = 0; i < mPASSWORD_CNT; ++i)
    {
        OLED_DrawSquare(mPASSWORD_DISP_X_INDEX + (mPASSWORD_DISP_SQUARE_WIDTH + 4) * i,
                        mPASSWORD_DISP_Y_INDEX,
                        mPASSWORD_DISP_X_INDEX + (mPASSWORD_DISP_SQUARE_WIDTH + 4) * i + mPASSWORD_DISP_SQUARE_WIDTH,
                        mPASSWORD_DISP_Y_INDEX + mPASSWORD_DISP_SQUARE_WIDTH);
    }

    return;
}


/**
 * @brief   在显示屏中显示输入密码的叉号
 * @param   void
 * @retval  void
 */
void vDisp_Password_Fork(uint8_t ucInputPasswordCnt)
{
    int i;

    for(i = 0; i < ucInputPasswordCnt; ++i)
    {
        OLED_DrawLine(mPASSWORD_DISP_X_INDEX + (mPASSWORD_DISP_SQUARE_WIDTH + 4) * i,
                      mPASSWORD_DISP_Y_INDEX,
                      mPASSWORD_DISP_X_INDEX + (mPASSWORD_DISP_SQUARE_WIDTH + 4) * i + mPASSWORD_DISP_SQUARE_WIDTH,
                      mPASSWORD_DISP_Y_INDEX + mPASSWORD_DISP_SQUARE_WIDTH);

        OLED_DrawLine(mPASSWORD_DISP_X_INDEX + (mPASSWORD_DISP_SQUARE_WIDTH + 4) * i,
                      mPASSWORD_DISP_Y_INDEX + mPASSWORD_DISP_SQUARE_WIDTH,
                      mPASSWORD_DISP_X_INDEX + (mPASSWORD_DISP_SQUARE_WIDTH + 4) * i + mPASSWORD_DISP_SQUARE_WIDTH,
                      mPASSWORD_DISP_Y_INDEX);
    }

    return;
}



/**
 * @brief   显示任务
 * @param   uint8_t ucKeyValue  按键值
 * @retval  void
 */
void vDisplay_Task(uint8_t ucKeyValue)
{
    static uint8_t ucInputPasswordCnt = 0;
    static uint32_t ulInputPasswrod = 0;
    static uint32_t ulNewPassword = 0;
    static uint8_t ucPasswordErrorCnt = 0;

    if(ucKeyValue == 0x0A)
    {
        // * 号的处理，进入修改密码模式
        if(gucMenuIndex == eMENU_INDEX_MANAGE_MODE)
        {
            gucMenuIndex = eMENU_INDEX_INPUT_SLEEP;
        }
        else
        {
            gucMenuIndex = eMENU_INDEX_MANAGE_MODE;
        }
    }
    else if(ucKeyValue == 0x0C)
    {
        // A 的处理，清除密码，用作忘记密码的特殊处理
        ucInputPasswordCnt = 0;
        ulInputPasswrod = 0;
        vUpdate_Password(0);
    }

    switch(gucMenuIndex)
    {
        case eMENU_INDEX_INPUT_SLEEP:   // 休眠模式
            vClear_Line_234();
            OLED_ShowChinese( 8, 16, "请输入密码解锁");

            ucInputPasswordCnt = 0;
            ulInputPasswrod = 0;

            // 显示输入密码的方框
            vDisp_Password_Square();
            gucMenuIndex = eMENU_INDEX_INPUT_PASSWORD;
            break;

        case eMENU_INDEX_INPUT_PASSWORD:    // 输入密码模式
            if(ucKeyValue <= 9)
            {
                // 按下的是 0-9
                vClear_One_Line(3);
                vClear_One_Line(4);

                vDisp_Password_Square();

                // 记录输入密码的位数和值
                ucInputPasswordCnt++;
                ulInputPasswrod = ulInputPasswrod * 10 + ucKeyValue;
                // 显示方框中的叉号表示选中
                vDisp_Password_Fork(ucInputPasswordCnt);

                if(ucInputPasswordCnt >= mPASSWORD_CNT)
                {
                    // 输入的密码和解锁密码比较
                    if(ulInputPasswrod == ulGet_Password())
                    {
                        vClear_Line_234();
                        OLED_ShowChinese( 8, 16, "密码正确已开锁");
                        gucMenuIndex = eMENU_INDEX_INPUT_SLEEP;
                        ucPasswordErrorCnt = 0;
                        gucBeepAlarmFlag = 0;
                    }
                    else
                    {
                        vClear_Line_234();
                        OLED_ShowChinese( 8, 16, "密码错误请重输");
                        gucMenuIndex = eMENU_INDEX_INPUT_SLEEP;

                        // 记录密码输错的次数用于报警
                        ucPasswordErrorCnt++;

                        if(ucPasswordErrorCnt >= mPASSWORD_MAX_ERROR_CNT)
                        {
                            // 连续多次输错密码报警
                            gucBeepAlarmFlag = 1;
                            ucPasswordErrorCnt = mPASSWORD_MAX_ERROR_CNT;
                        }
                    }

                    //密码的位数和值清0
                    ucInputPasswordCnt = 0;
                    ulInputPasswrod = 0;

                }
            }
            else if((ucKeyValue == 0x0B) && (ucInputPasswordCnt >= 1))
            {
                // 按下的是 # 表示删除输入的密码
                ucInputPasswordCnt--;
                ulInputPasswrod /= 10;

                vClear_One_Line(3);
                vClear_One_Line(4);

                // 显示输入密码的方框
                vDisp_Password_Square();
                // 显示方框中的叉号表示选中
                vDisp_Password_Fork(ucInputPasswordCnt);
            }

            break;

        case eMENU_INDEX_MANAGE_MODE:   // 修改密码模式
            if(ucKeyValue == 0x0A)
            {
                // * 号表示进入修改密码模式
                vClear_Line_234();
                ucInputPasswordCnt = 0;
                ulInputPasswrod = 0;

                OLED_ShowChinese( 0, 16, "请输入管理员密码");
                // 显示输入密码的方框
                vDisp_Password_Square();
            }
            else if(ucKeyValue <= 9)    // 按下的是 0-9
            {
                vClear_Line_234();
                OLED_ShowChinese( 0, 16, "请输入管理员密码");

                // 显示输入密码的方框
                vDisp_Password_Square();

                // 记录输入密码的位数和值
                ucInputPasswordCnt++;
                ulInputPasswrod = ulInputPasswrod * 10 + ucKeyValue;
                // 显示方框中的叉号表示选中
                vDisp_Password_Fork(ucInputPasswordCnt);

                if(ucInputPasswordCnt >= mPASSWORD_CNT)
                {
                    // 密码和解锁密码比较
                    if(ulInputPasswrod == ulGet_Password())
                    {
                        vClear_Line_234();
                        OLED_ShowChinese( 16, 16, "请输入新密码");
                        vDisp_Password_Square();
                        gucMenuIndex = eMENU_INDEX_CHANGE_PASSWORD_1;
                    }
                    else
                    {
                        vClear_Line_234();
                        OLED_ShowChinese( 8, 16, "密码错误请重输");

                        // 记录密码输错的次数用于报警
                        ucPasswordErrorCnt++;

                        if(ucPasswordErrorCnt >= mPASSWORD_MAX_ERROR_CNT)
                        {
                            // 连续多次输错密码报警
                            gucBeepAlarmFlag = 1;
                            ucPasswordErrorCnt = mPASSWORD_MAX_ERROR_CNT;
                        }

                        gucMenuIndex = eMENU_INDEX_MANAGE_MODE;
                    }

                    ucInputPasswordCnt = 0;
                    ulInputPasswrod = 0;

                }
            }
            else if((ucKeyValue == 0x0B) && (ucInputPasswordCnt >= 1))
            {
                // 按下的是 # 表示删除输入的密码
                ucInputPasswordCnt--;
                ulInputPasswrod /= 10;

                vClear_One_Line(3);
                vClear_One_Line(4);

                vDisp_Password_Square();
                vDisp_Password_Fork(ucInputPasswordCnt);
            }

            break;

        case eMENU_INDEX_CHANGE_PASSWORD_1:
            if(ucKeyValue <= 9)
            {
                vClear_One_Line(3);
                vClear_One_Line(4);

                vDisp_Password_Square();

                // 记录输入密码的位数和值
                ucInputPasswordCnt++;
                ulInputPasswrod = ulInputPasswrod * 10 + ucKeyValue;
                // 显示方框中的叉号表示选中
                vDisp_Password_Fork(ucInputPasswordCnt);

                if(ucInputPasswordCnt >= mPASSWORD_CNT)
                {
                    // 记录第一次输入的新密码，新密码需要输入两次
                    ulNewPassword = ulInputPasswrod;

                    vClear_Line_234();
                    OLED_ShowChinese( 0, 16, "请再次输入新密码");

                    vDisp_Password_Square();
                    gucMenuIndex = eMENU_INDEX_CHANGE_PASSWORD_2;

                    ucInputPasswordCnt = 0;
                    ulInputPasswrod = 0;

                }
            }
            else if((ucKeyValue == 0x0B) && (ucInputPasswordCnt >= 1))
            {
                // 按下的是 # 表示删除输入的密码
                ucInputPasswordCnt--;
                ulInputPasswrod /= 10;

                vClear_One_Line(3);
                vClear_One_Line(4);

                vDisp_Password_Square();
                vDisp_Password_Fork(ucInputPasswordCnt);
            }

            break;

        case eMENU_INDEX_CHANGE_PASSWORD_2:
            if(ucKeyValue <= 9)
            {
                vClear_One_Line(3);
                vClear_One_Line(4);

                vDisp_Password_Square();

                ucInputPasswordCnt++;
                ulInputPasswrod = ulInputPasswrod * 10 + ucKeyValue;
                vDisp_Password_Fork(ucInputPasswordCnt);

                if(ucInputPasswordCnt >= mPASSWORD_CNT)
                {
                    if(ulInputPasswrod == ulNewPassword)    // 第二次输入的新密码和第一次输入的对比
                    {
                        vClear_Line_234();
                        OLED_ShowChinese( 16, 16, "密码修改成功");
                        // 存储新密码
                        vUpdate_Password(ulNewPassword);
                        ucPasswordErrorCnt = 0;
                        // 清除报警标志
                        gucBeepAlarmFlag = 0;
                        gucMenuIndex = eMENU_INDEX_INPUT_SLEEP;
                    }
                    else
                    {
                        vClear_Line_234();
                        // 第二次输入的新密码和第一次输入的新密码不一致
                        OLED_ShowChinese( 8, 16, "密码错误请重输");
                        vDisp_Password_Square();
                        gucMenuIndex = eMENU_INDEX_CHANGE_PASSWORD_1;
                    }

                    ucInputPasswordCnt = 0;
                    ulInputPasswrod = 0;

                }
            }
            else if((ucKeyValue == 0x0B) && (ucInputPasswordCnt >= 1))
            {
                // 按下的是 # 表示删除输入的密码
                ucInputPasswordCnt--;
                ulInputPasswrod /= 10;

                vClear_One_Line(3);
                vClear_One_Line(4);

                vDisp_Password_Square();
                vDisp_Password_Fork(ucInputPasswordCnt);
            }

            break;

        case eMENU_INDEX_MAX:
            break;

        default:
            break;
    }

    OLED_Refresh();

    return;
}

/**
 * @brief   获取报警标志
 * @param   void
 * @retval  uint8_t 报警标志
 */
uint8_t vGet_Beep_Alarm_Flag(void)
{
    return gucBeepAlarmFlag;
}

/**
 * @brief   蜂鸣器报警任务
 * @param   void
 * @retval  void
 */
void vBeep_Alarm_Task(void)
{
    static uint8_t ucBeepTaskStep = 0;
    static uint32_t ulBeepTaskLastTick = 0;
    uint32_t ulBeepTaskCurrTick;

    if(vGet_Beep_Alarm_Flag() == 1)
    {
        switch ( ucBeepTaskStep )
        {
            case 0 :
                // 记录当前的时基
                ulBeepTaskLastTick = HAL_GetTick();
                ucBeepTaskStep = 1;
                break;

            case 1 :
                ulBeepTaskCurrTick = HAL_GetTick();

                if ( ulBeepTaskCurrTick >= ulBeepTaskLastTick )
                {
                    if ( ulBeepTaskCurrTick - ulBeepTaskLastTick > 500 )
                    {
                        ucBeepTaskStep = 0;
                        // 蜂鸣器电平翻转
                        vBeep_Toggle();
                    }
                }
                else
                {
                    /** 溢出处理 */
                    if ( ulBeepTaskCurrTick + ( ~ulBeepTaskLastTick ) > 500 )
                    {
                        ucBeepTaskStep = 0;
                        // 蜂鸣器电平翻转
                        vBeep_Toggle();
                    }
                }

                break;

            default:
                break;
        }
    }
    else
    {
        vBeep_Off();
    }
}
